//! 市场数据API
//! 
//! 提供统一的市场数据查询接口，支持所有产品线

use crate::errors::{BinanceError, Result};
use crate::rest::RestClient;
use crate::models::*;

/// 市场数据API
pub struct MarketApi<'a> {
    client: &'a RestClient,
}

impl<'a> MarketApi<'a> {
    pub fn new(client: &'a RestClient) -> Self {
        Self { client }
    }

    /// 获取服务器时间
    pub async fn get_server_time(&self) -> Result<ServerTime> {
        // 根据产品类型使用不同的API路径
        let endpoint = match self.client.config().product_type {
            crate::ProductType::Spot => "/api/v3/time",
            crate::ProductType::UsdM => "/fapi/v1/time",
            crate::ProductType::CoinM => "/dapi/v1/time",
            crate::ProductType::Options => "/api/v3/time", // 期权测试网使用现货API
            crate::ProductType::Portfolio => "/api/v3/time",
        };
        
        // 打印完整的API调用URL
        let full_url = format!("{}{}", self.client.config().rest_base_url(), endpoint);
        tracing::info!("[MARKET_API] 调用服务器时间API: {}", full_url);
        
        let response = self.client.get(endpoint, false).await?;
        let server_time: ServerTime = serde_json::from_str(&response)?;
        Ok(server_time)
    }

    /// 获取交易对信息
    pub async fn get_exchange_info(&self) -> Result<ExchangeInfo> {
        // 根据产品类型使用不同的API路径
        let endpoint = match self.client.config().product_type {
            crate::ProductType::Spot => "/api/v3/exchangeInfo",
            crate::ProductType::UsdM => "/fapi/v1/exchangeInfo",
            crate::ProductType::CoinM => "/dapi/v1/exchangeInfo",
            crate::ProductType::Options => "/api/v3/exchangeInfo", // 期权测试网使用现货API
            crate::ProductType::Portfolio => "/api/v3/exchangeInfo",
        };
        
        // 打印完整的API调用URL
        let full_url = format!("{}{}", self.client.config().rest_base_url(), endpoint);
        tracing::info!("[MARKET_API] 调用交易对信息API: {}", full_url);
        
        let response = self.client.get(endpoint, false).await?;
        let exchange_info: ExchangeInfo = serde_json::from_str(&response)?;
        Ok(exchange_info)
    }

    /// 获取24小时价格统计
    pub async fn get_24hr_ticker(&self, symbol: Option<&str>) -> Result<Ticker24hr> {
        // 根据产品类型使用不同的API路径
        let base_path = match self.client.config().product_type {
            crate::ProductType::Spot => "/api/v3/ticker/24hr",
            crate::ProductType::UsdM => "/fapi/v1/ticker/24hr",
            crate::ProductType::CoinM => "/dapi/v1/ticker/24hr",
            crate::ProductType::Options => "/api/v3/ticker/24hr", // 期权测试网使用现货API
            crate::ProductType::Portfolio => "/api/v3/ticker/24hr",
        };
        
        let endpoint = if let Some(sym) = symbol {
            format!("{}?symbol={}", base_path, sym)
        } else {
            base_path.to_string()
        };
        
        // 打印完整的API调用URL
        let full_url = format!("{}{}", self.client.config().rest_base_url(), endpoint);
        tracing::info!("[MARKET_API] 调用24小时价格统计API: {}", full_url);
        
        let response = self.client.get(&endpoint, false).await?;
        
        // 添加调试日志，打印原始响应数据
        tracing::debug!("[MARKET_API] 24小时价格统计原始响应: {}", response);
        tracing::info!("[MARKET_API] 24小时价格统计响应长度: {} 字符", response.len());
        
        // 对于币本位合约，打印前500个字符用于分析
        if self.client.config().product_type == crate::ProductType::CoinM {
            let preview = if response.len() > 500 {
                format!("{}...", &response[..500])
            } else {
                response.clone()
            };
            tracing::info!("[MARKET_API] 币本位合约响应预览: {}", preview);
            
            // 检查响应是否是数组格式
            if response.trim_start().starts_with('[') {
                tracing::info!("[MARKET_API] 币本位合约返回数组格式，需要特殊处理");
            }
        }
        
        // 对于币本位合约，响应是数组格式，需要特殊处理
        let ticker = if self.client.config().product_type == crate::ProductType::CoinM {
            // 币本位合约返回数组，取第一个元素
            let tickers: Vec<Ticker24hr> = serde_json::from_str(&response)?;
            if tickers.is_empty() {
                return Err(crate::errors::BinanceError::ParseError("币本位合约返回空数组".to_string()));
            }
            tickers[0].clone()
        } else {
            // 其他产品类型直接解析
            serde_json::from_str(&response)?
        };
        
        Ok(ticker)
    }

    /// 获取最新价格
    pub async fn get_price(&self, symbol: Option<&str>) -> Result<PriceInfo> {
        // 根据产品类型使用不同的API路径
        let base_path = match self.client.config().product_type {
            crate::ProductType::Spot => "/api/v3/ticker/price",
            crate::ProductType::UsdM => "/fapi/v1/ticker/price",
            crate::ProductType::CoinM => "/dapi/v1/ticker/price",
            crate::ProductType::Options => "/api/v3/ticker/price", // 期权测试网使用现货API
            crate::ProductType::Portfolio => "/api/v3/ticker/price",
        };
        
        let endpoint = if let Some(sym) = symbol {
            format!("{}?symbol={}", base_path, sym)
        } else {
            base_path.to_string()
        };
        
        // 打印完整的API调用URL
        let full_url = format!("{}{}", self.client.config().rest_base_url(), endpoint);
        tracing::info!("[MARKET_API] 调用最新价格API: {}", full_url);
        
        let response = self.client.get(&endpoint, false).await?;
        
        // 添加调试日志，打印原始响应数据
        tracing::debug!("[MARKET_API] 最新价格原始响应: {}", response);
        tracing::info!("[MARKET_API] 最新价格响应长度: {} 字符", response.len());
        
        // 对于币本位合约，打印前500个字符用于分析
        if self.client.config().product_type == crate::ProductType::CoinM {
            let preview = if response.len() > 500 {
                format!("{}...", &response[..500])
            } else {
                response.clone()
            };
            tracing::info!("[MARKET_API] 币本位合约价格响应预览: {}", preview);
            
            // 检查响应是否是数组格式
            if response.trim_start().starts_with('[') {
                tracing::info!("[MARKET_API] 币本位合约价格返回数组格式，需要特殊处理");
            }
        }
        
        // 对于币本位合约，响应可能是数组格式，需要特殊处理
        let price = if self.client.config().product_type == crate::ProductType::CoinM {
            // 币本位合约可能返回数组，取第一个元素
            if response.trim_start().starts_with('[') {
                let prices: Vec<PriceInfo> = serde_json::from_str(&response)?;
                if prices.is_empty() {
                    return Err(crate::errors::BinanceError::ParseError("币本位合约价格返回空数组".to_string()));
                }
                prices[0].clone()
            } else {
                // 如果不是数组，直接解析
                serde_json::from_str(&response)?
            }
        } else {
            // 其他产品类型直接解析
            serde_json::from_str(&response)?
        };
        
        Ok(price)
    }

    /// 获取最优挂单价格
    pub async fn get_book_ticker(&self, symbol: Option<&str>) -> Result<BookTicker> {
        let endpoint = if let Some(sym) = symbol {
            format!("/ticker/bookTicker?symbol={}", sym)
        } else {
            "/ticker/bookTicker".to_string()
        };
        
        let response = self.client.get(&endpoint, false).await?;
        let book_ticker: BookTicker = serde_json::from_str(&response)?;
        Ok(book_ticker)
    }

    /// 获取订单簿
    pub async fn get_order_book(&self, symbol: &str, limit: Option<u32>) -> Result<OrderBook> {
        let mut endpoint = format!("/depth?symbol={}", symbol);
        if let Some(l) = limit {
            endpoint.push_str(&format!("&limit={}", l));
        }
        
        let response = self.client.get(&endpoint, false).await?;
        let order_book: OrderBook = serde_json::from_str(&response)?;
        Ok(order_book)
    }

    /// 获取K线数据
    pub async fn get_klines(
        &self,
        symbol: &str,
        interval: &str,
        limit: Option<u32>,
        start_time: Option<u64>,
        end_time: Option<u64>,
    ) -> Result<Vec<Kline>> {
        // 根据产品类型使用不同的API路径
        let base_path = match self.client.config().product_type {
            crate::ProductType::Spot => "/api/v3/klines",
            crate::ProductType::UsdM => "/fapi/v1/klines",
            crate::ProductType::CoinM => "/dapi/v1/klines",
            crate::ProductType::Options => "/api/v3/klines", // 期权测试网使用现货API
            crate::ProductType::Portfolio => "/api/v3/klines",
        };
        
        let mut endpoint = format!("{}?symbol={}&interval={}", base_path, symbol, interval);
        
        if let Some(l) = limit {
            endpoint.push_str(&format!("&limit={}", l));
        }
        if let Some(start) = start_time {
            endpoint.push_str(&format!("&startTime={}", start));
        }
        if let Some(end) = end_time {
            endpoint.push_str(&format!("&endTime={}", end));
        }
        
        let response = self.client.get(&endpoint, false).await?;
        let klines: Vec<Vec<serde_json::Value>> = serde_json::from_str(&response)?;
        
        let result: Result<Vec<Kline>> = klines.into_iter()
            .map(|kline| {
                Ok(Kline {
                    open_time: kline[0].as_u64().unwrap_or(0),
                    open: kline[1].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse open price: {}", e)))?,
                    high: kline[2].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse high price: {}", e)))?,
                    low: kline[3].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse low price: {}", e)))?,
                    close: kline[4].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse close price: {}", e)))?,
                    volume: kline[5].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse volume: {}", e)))?,
                    close_time: kline[6].as_u64().unwrap_or(0),
                    quote_asset_volume: kline[7].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse quote asset volume: {}", e)))?,
                    number_of_trades: kline[8].as_u64().unwrap_or(0),
                    taker_buy_base_asset_volume: kline[9].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse taker buy base asset volume: {}", e)))?,
                    taker_buy_quote_asset_volume: kline[10].as_str().unwrap_or("0").parse().map_err(|e| BinanceError::ParseError(format!("Failed to parse taker buy quote asset volume: {}", e)))?,
                    ignore: kline[11].as_str().unwrap_or("0").parse().unwrap_or(rust_decimal::Decimal::ZERO),
                })
            })
            .collect();
        
        result
    }

    /// 获取历史成交记录
    pub async fn get_trades(&self, symbol: &str, limit: Option<u32>) -> Result<Vec<Trade>> {
        let mut endpoint = format!("/trades?symbol={}", symbol);
        if let Some(l) = limit {
            endpoint.push_str(&format!("&limit={}", l));
        }
        
        let response = self.client.get(&endpoint, false).await?;
        let trades: Vec<Trade> = serde_json::from_str(&response)?;
        Ok(trades)
    }

    /// 获取历史成交记录（带时间范围）
    pub async fn get_historical_trades(
        &self,
        symbol: &str,
        from_id: Option<u64>,
        limit: Option<u32>,
    ) -> Result<Vec<Trade>> {
        let mut endpoint = format!("/historicalTrades?symbol={}", symbol);
        
        if let Some(id) = from_id {
            endpoint.push_str(&format!("&fromId={}", id));
        }
        if let Some(l) = limit {
            endpoint.push_str(&format!("&limit={}", l));
        }
        
        let response = self.client.get(&endpoint, false).await?;
        let trades: Vec<Trade> = serde_json::from_str(&response)?;
        Ok(trades)
    }

    /// 获取聚合成交记录
    pub async fn get_agg_trades(
        &self,
        symbol: &str,
        from_id: Option<u64>,
        start_time: Option<u64>,
        end_time: Option<u64>,
        limit: Option<u32>,
    ) -> Result<Vec<AggTrade>> {
        let mut endpoint = format!("/aggTrades?symbol={}", symbol);
        
        if let Some(id) = from_id {
            endpoint.push_str(&format!("&fromId={}", id));
        }
        if let Some(start) = start_time {
            endpoint.push_str(&format!("&startTime={}", start));
        }
        if let Some(end) = end_time {
            endpoint.push_str(&format!("&endTime={}", end));
        }
        if let Some(l) = limit {
            endpoint.push_str(&format!("&limit={}", l));
        }
        
        let response = self.client.get(&endpoint, false).await?;
        let agg_trades: Vec<AggTrade> = serde_json::from_str(&response)?;
        Ok(agg_trades)
    }
}
